module uart_memory (
    input clk,
    input resetn,
    input uart_rx,
    output uart_tx,
    input memory_en,
    input mem_valid,
    input mem_instr,
    input [31:0] mem_addr,
    input [31:0] mem_wdata,
    input [3:0] mem_wstrb,
    output reg [31:0] mem_rdata,
    output reg mem_ready
);
parameter CLK_FREQ=5000000;	//系统时钟频率
parameter UART_BPS=9600;		//波特率

wire [7:0] uart_rdata;
reg [7:0] uart_wdata;
reg uart_start;
wire uart_rxdone;
wire uart_txdone;
uart_recv
#(
	.CLK_FREQ	(CLK_FREQ),
	.UART_BPS	(UART_BPS)
)
u_uart_recv(
	.clk			(clk),
	.rst_n		(resetn),
	
	.uart_rxd	(uart_rx),
	.uart_data	(uart_rdata),
	.uart_done	(uart_rxdone)
);
uart_txd
#(
	.CLK_FREQ	(CLK_FREQ),
	.UART_BPS	(UART_BPS)
)
u_uart_txd(
	.clk			(clk),
	.rst_n		(resetn),

	.uart_txd	(uart_tx),
	.uart_en		(uart_start),

	.uart_data	(uart_wdata),
    .uart_tx_done (uart_txdone)
	);
reg uart_rxdone_r0;
wire uart_rxdone_pos;
always @(posedge clk) begin
    uart_rxdone_r0 <= uart_rxdone;
end
assign uart_rxdone_pos = uart_rxdone &(~uart_rxdone_r0);

reg [1:0] uart_state;
reg [3:0] uart_cnt;
reg uart_send_state;
parameter uart_send = 1'b0;
parameter uart_tx_wait = 1'b1;

parameter uart_init = 2'b00;
parameter uart_wait = 2'b01;
parameter uart_work = 2'b10;

reg [15:0] uart_delay_cnt;
always@(posedge  clk or negedge resetn)begin
    if(!resetn) begin
        uart_delay_cnt <= 16'h0;
    end
    else if(uart_state == uart_wait) begin
        uart_delay_cnt <= uart_delay_cnt + 1'b1;
    end
    else begin
        uart_delay_cnt <= 16'h0;
    end
end
reg [27:0] overtime;
reg overtime_oe;
wire overtime_flag;
assign overtime_flag = (overtime == 28'd27000000) ? 1'b1 : 1'b0;
always@(posedge clk or negedge overtime_oe)begin
    if(!overtime_oe) begin
        overtime <= 28'd0;
    end
    else begin
        if(overtime != 28'd27000000)begin
            overtime <= overtime + 1'b1;
        end
        else begin
            overtime <= overtime;
        end
    end
end
always@(posedge clk or negedge resetn) begin
    if(!resetn) begin
        mem_ready <= 1'b0;
        uart_wdata <= 8'h0;
        uart_state <= uart_init;
        uart_cnt <= 4'h0;
        uart_start <= 1'b0;
        uart_send_state <= uart_send;
        overtime_oe <= 1'b0;
    end
    else begin
        case(uart_state)
        uart_init:begin
            case(uart_cnt)
            4'h0:begin
                uart_wdata <= 8'hfe;
                case(uart_send_state)
                uart_send:begin
                    uart_send_state <= uart_tx_wait;
                    uart_start <= 1'b1;
                end
                uart_tx_wait:begin
                    uart_start <= 1'b0;
                    if(uart_txdone)begin
                        uart_send_state <= uart_send;
                        uart_cnt <= 4'h1;
                    end
                end
                endcase
            end
            4'h1:begin
                uart_wdata <= 8'hfe;
                case(uart_send_state)
                uart_send:begin
                    uart_send_state <= uart_tx_wait;
                    uart_start <= 1'b1;
                end
                uart_tx_wait:begin
                    uart_start <= 1'b0;
                    if(uart_txdone)begin
                        uart_send_state <= uart_send;
                        uart_cnt <= 4'h2;
                    end
                end
                endcase
            end
            4'h2:begin
                uart_wdata <= 8'hfe;
                case(uart_send_state)
                uart_send:begin
                    uart_send_state <= uart_tx_wait;
                    uart_start <= 1'b1;
                end
                uart_tx_wait:begin
                    uart_start <= 1'b0;
                    if(uart_txdone)begin
                        uart_send_state <= uart_send;
                        uart_cnt <= 4'h3;
                    end
                end
                endcase
            end
            4'h3:begin
                uart_wdata <= 8'hfe;
                case(uart_send_state)
                uart_send:begin
                    uart_send_state <= uart_tx_wait;
                    uart_start <= 1'b1;
                end
                uart_tx_wait:begin
                    uart_start <= 1'b0;
                    if(uart_txdone)begin
                        uart_send_state <= uart_send;
                        uart_cnt <= 4'h4;
                    end
                end
                endcase
            end
            4'h4:begin
                uart_wdata <= 8'hfe;
                case(uart_send_state)
                uart_send:begin
                    uart_send_state <= uart_tx_wait;
                    uart_start <= 1'b1;
                end
                uart_tx_wait:begin
                    uart_start <= 1'b0;
                    if(uart_txdone)begin
                        uart_send_state <= uart_send;
                        uart_cnt <= 4'h5;
                    end
                end
                endcase
            end
            4'h5:begin
                uart_wdata <= 8'hfe;
                case(uart_send_state)
                uart_send:begin
                    uart_send_state <= uart_tx_wait;
                    uart_start <= 1'b1;
                end
                uart_tx_wait:begin
                    uart_start <= 1'b0;
                    if(uart_txdone)begin
                        uart_send_state <= uart_send;
                        uart_cnt <= 4'h6;
                    end
                end
                endcase
            end
            4'h6:begin
                uart_wdata <= 8'hfe;
                case(uart_send_state)
                uart_send:begin
                    uart_send_state <= uart_tx_wait;
                    uart_start <= 1'b1;
                end
                uart_tx_wait:begin
                    uart_start <= 1'b0;
                    if(uart_txdone)begin
                        uart_send_state <= uart_send;
                        uart_cnt <= 4'h0;
                        uart_state <= uart_wait;
                    end
                end
                endcase
            end
            default:begin
                uart_cnt <= uart_cnt;
            end
            endcase
        end
        uart_wait:begin
            if(uart_delay_cnt == 16'd49999) begin
                uart_state <= uart_work;
                uart_send_state <= uart_send;
                uart_cnt <= 4'h0;
                mem_ready <= 1'b0;
            end
        end
        uart_work:begin
            if(mem_valid == 1'b0) begin
                mem_ready <= 1'b0;
                uart_cnt <= 4'h0;
            end

            if((mem_addr[31:16] == 16'h0)&&(memory_en == 1'b1)) begin
                if(mem_valid)begin
                    if(mem_wstrb == 4'b0000)begin
                        case(uart_cnt)
                        4'h0:begin
                            overtime_oe <= 1'b0;
                            if(mem_instr) begin
                                uart_wdata <= 8'h80;//请求取指令
                            end
                            else begin
                                uart_wdata <= 8'hA0;//读数据
                            end
                            case(uart_send_state)
                            uart_send:begin
                                uart_send_state <= uart_tx_wait;
                                uart_start <= 1'b1;
                            end
                            uart_tx_wait:begin
                                uart_start <= 1'b0;
                                if(uart_txdone)begin
                                    uart_send_state <= uart_send;
                                    uart_cnt <= 4'h1;
                                end
                            end
                            endcase
                        end
                        4'h1:begin
                            uart_wdata <= mem_addr[15:8];//发送地址
                            case(uart_send_state)
                            uart_send:begin
                                uart_send_state <= uart_tx_wait;
                                uart_start <= 1'b1;
                            end
                            uart_tx_wait:begin
                                uart_start <= 1'b0;
                                if(uart_txdone)begin
                                    uart_send_state <= uart_send;
                                    uart_cnt <= 4'h2;
                                end
                            end
                            endcase
                        end
                        4'h2:begin
                            uart_wdata <= mem_addr[7:0];//发送地址
                            case(uart_send_state)
                            uart_send:begin
                                uart_send_state <= uart_tx_wait;
                                uart_start <= 1'b1;
                            end
                            uart_tx_wait:begin
                                uart_start <= 1'b0;
                                if(uart_txdone)begin
                                    overtime_oe <= 1'b1;//超时计数器开启
                                    uart_send_state <= uart_send;
                                    uart_cnt <= 4'h3;
                                end
                            end
                            endcase
                        end
                        4'h3:begin
                            if(uart_rxdone_pos) begin
                                mem_rdata[31:24] <= uart_rdata;//
                                uart_cnt <= 4'h4;
                            end
                            if(overtime_flag)begin
                                uart_state <= uart_init;
                                overtime_oe <= 1'b0;
                            end
                        end
                        4'h4:begin
                            if(uart_rxdone_pos) begin
                                mem_rdata[23:16] <= uart_rdata;
                                uart_cnt <= 3'h5;
                            end
                            if(overtime_flag)begin
                                uart_state <= uart_init;
                                overtime_oe <= 1'b0;
                            end
                        end
                        4'h5:begin
                            if(uart_rxdone_pos) begin
                                mem_rdata[15:8] <= uart_rdata;
                                uart_cnt <= 4'h6;
                            end
                            if(overtime_flag)begin
                                uart_state <= uart_init;
                                overtime_oe <= 1'b0;
                            end
                        end
                        4'h6:begin
                            if(uart_rxdone_pos) begin
                                mem_rdata[7:0] <= uart_rdata;
                                uart_cnt <= 4'h7;
                                mem_ready <= 1'b1;
                            end
                            if(overtime_flag)begin
                                uart_state <= uart_init;
                                overtime_oe <= 1'b0;
                            end
                        end

                        4'h7:begin
                            overtime_oe <= 1'b0;
                            mem_ready <= mem_ready;
                        end
                        endcase
                    end
                    else begin
                        
                        case(uart_cnt)
                        4'h0:begin
                            uart_wdata <= {4'h9,mem_wstrb[3:0]};//8'h9x命令
                            case(uart_send_state)
                            uart_send:begin
                                uart_send_state <= uart_tx_wait;
                                uart_start <= 1'b1;
                            end
                            uart_tx_wait:begin
                                uart_start <= 1'b0;
                                if(uart_txdone)begin
                                    uart_send_state <= uart_send;
                                    uart_cnt <= 4'h1;
                                end
                            end
                            endcase
                        end
                        4'h1:begin
                            uart_wdata <= mem_addr[15:8];//发送地址
                            case(uart_send_state)
                            uart_send:begin
                                uart_send_state <= uart_tx_wait;
                                uart_start <= 1'b1;
                            end
                            uart_tx_wait:begin
                                uart_start <= 1'b0;
                                if(uart_txdone)begin
                                    uart_send_state <= uart_send;
                                    uart_cnt <= 4'h2;
                                end
                            end
                            endcase
                        end
                        4'h2:begin
                            uart_wdata <= mem_addr[7:0];//发送地址
                            case(uart_send_state)
                            uart_send:begin
                                uart_send_state <= uart_tx_wait;
                                uart_start <= 1'b1;
                            end
                            uart_tx_wait:begin
                                uart_start <= 1'b0;
                                if(uart_txdone)begin
                                    uart_send_state <= uart_send;
                                    uart_cnt <= 4'h3;
                                end
                            end
                            endcase
                        end
                        4'h3:begin
                            uart_wdata <= mem_wdata[31:24];
                            case(uart_send_state)
                            uart_send:begin
                                uart_send_state <= uart_tx_wait;
                                uart_start <= 1'b1;
                            end
                            uart_tx_wait:begin
                                uart_start <= 1'b0;
                                if(uart_txdone)begin
                                    case(mem_wstrb)
                                        4'b0001:uart_cnt <= 4'h7;
                                        4'b0010:uart_cnt <= 4'h7;
                                        4'b0100:uart_cnt <= 4'h7;
                                        4'b1000:uart_cnt <= 4'h7;
                                        default:uart_cnt <= 4'h4;
                                    endcase
                                    uart_send_state <= uart_send;
                                end
                            end
                            endcase
                        end

                        4'h4:begin
                            uart_wdata <= mem_wdata[23:16];
                            case(uart_send_state)
                            uart_send:begin
                                uart_send_state <= uart_tx_wait;
                                uart_start <= 1'b1;
                            end
                            uart_tx_wait:begin
                                uart_start <= 1'b0;
                                if(uart_txdone)begin
                                    case(mem_wstrb)
                                        4'b0011:uart_cnt <= 4'h7;
                                        4'b1100:uart_cnt <= 4'h7;
                                        default:uart_cnt <= 4'h5;
                                    endcase
                                    uart_send_state <= uart_send;
                                end
                            end
                            endcase
                        end

                        4'h5:begin
                            uart_wdata <= mem_wdata[15:8];
                            case(uart_send_state)
                            uart_send:begin
                                uart_send_state <= uart_tx_wait;
                                uart_start <= 1'b1;
                            end
                            uart_tx_wait:begin
                                uart_start <= 1'b0;
                                if(uart_txdone)begin
                                    uart_send_state <= uart_send;
                                    uart_cnt <= 4'h6;
                                end
                            end
                            endcase
                        end

                        4'h6:begin
                            uart_wdata <= mem_wdata[7:0];
                            case(uart_send_state)
                            uart_send:begin
                                uart_send_state <= uart_tx_wait;
                                uart_start <= 1'b1;
                            end
                            uart_tx_wait:begin
                                uart_start <= 1'b0;
                                if(uart_txdone)begin
                                    uart_send_state <= uart_send;
                                    uart_cnt <= 4'h7;
                                end
                            end
                            endcase
                        end

                        4'h7:begin
                            uart_cnt <= 4'h7;
                            mem_ready <= 1'b1;
                        end

                        endcase
                    end
                end
            end
        end
        endcase
    end
end    
endmodule